/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * Copyright by The HDF Group.                                               *
 * Copyright by the Board of Trustees of the University of Illinois.         *
 * All rights reserved.                                                      *
 *                                                                           *
 * This file is part of HDF5.  The full HDF5 copyright notice, including     *
 * terms governing use, modification, and redistribution, is contained in    *
 * the files COPYING and Copyright.html.  COPYING can be found at the root   *
 * of the source code distribution tree; Copyright.html can be found at the  *
 * root level of an installed copy of the electronic HDF5 document set and   *
 * is linked from the top-level documents page.  It can also be found at     *
 * http://hdfgroup.org/HDF5/doc/Copyright.html.  If you do not have          *
 * access to either file, you may request a copy from help@hdfgroup.org.     *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include "H5IMprivate.h"
#include "H5LTprivate.h"
#include <string.h>
#include <stdlib.h>

/*-------------------------------------------------------------------------
 * Function: H5IMmake_image_8bit
 *
 * Purpose: Creates and writes an image an 8 bit image
 *
 * Return: Success: 0, Failure: -1
 *
 * Programmer: Pedro Vicente Nunes, pvn@ncsa.uiuc.edu
 *
 * Date: June 13, 2001
 *
 * Comments:
 *  based on HDF5 Image and Palette Specification
 *  http://hdf.ncsa.uiuc.edu/HDF5/H5Image/ImageSpec.html
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */

herr_t H5IMmake_image_8bit( hid_t loc_id,
                            const char *dset_name,
                            hsize_t width,
                            hsize_t height,
                            const unsigned char *buffer )
{
 hsize_t  dims[IMAGE8_RANK];

  /* Initialize the image dimensions */
 dims[0] = height;
 dims[1] = width;

 /* Make the dataset */
 if ( H5LTmake_dataset( loc_id, dset_name, IMAGE8_RANK, dims, H5T_NATIVE_UCHAR, buffer ) < 0)
  return -1;

 /* Attach the CLASS attribute */
 if ( H5LTset_attribute_string( loc_id, dset_name, "CLASS", IMAGE_CLASS ) < 0)
  return -1;

 /* Attach the VERSION attribute */
 if ( H5LTset_attribute_string( loc_id, dset_name, "IMAGE_VERSION", IMAGE_VERSION ) < 0)
  return -1;

 /* Attach the IMAGE_SUBCLASS attribute */
 if ( H5LTset_attribute_string( loc_id, dset_name, "IMAGE_SUBCLASS", "IMAGE_INDEXED" ) < 0)
  return -1;

 return 0;
}

/*-------------------------------------------------------------------------
 * Function: H5IMmake_image_24bit
 *
 * Purpose:
 *
 * Return: Success: 0, Failure: -1
 *
 * Programmer: Pedro Vicente Nunes, pvn@ncsa.uiuc.edu
 *
 * Date: June 13, 2001
 *
 * Comments:
 *  based on HDF5 Image and Palette Specification
 *  http://hdf.ncsa.uiuc.edu/HDF5/H5Image/ImageSpec.html
 *
 * Interlace Mode Dimensions in the Dataspace
 * INTERLACE_PIXEL [height][width][pixel components]
 * INTERLACE_PLANE [pixel components][height][width]
 *
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */

herr_t H5IMmake_image_24bit( hid_t loc_id,
                             const char *dset_name,
                             hsize_t width,
                             hsize_t height,
                             const char *interlace,
                             const unsigned char *buffer )
{
 hsize_t  dims[IMAGE24_RANK];

 /* Initialize the image dimensions */

 if ( strcmp( interlace, "INTERLACE_PIXEL" ) == 0 )
 {
  /* Number of color planes is defined as the third dimension */
  dims[0] = height;
  dims[1] = width;
  dims[2] = IMAGE24_RANK;
 }
 else
 if ( strcmp( interlace, "INTERLACE_PLANE" ) == 0 )
 {
  /* Number of color planes is defined as the first dimension */
  dims[0] = IMAGE24_RANK;
  dims[1] = height;
  dims[2] = width;
 }
 else return -1;

 /* Make the dataset */
 if ( H5LTmake_dataset( loc_id, dset_name, IMAGE24_RANK, dims, H5T_NATIVE_UCHAR, buffer ) < 0)
  return -1;

 /* Attach the CLASS attribute */
 if ( H5LTset_attribute_string( loc_id, dset_name, "CLASS", IMAGE_CLASS ) < 0)
  return -1;

 /* Attach the VERSION attribute */
 if ( H5LTset_attribute_string( loc_id, dset_name, "IMAGE_VERSION", IMAGE_VERSION ) < 0)
  return -1;

 /* Attach the IMAGE_SUBCLASS attribute */
 if ( H5LTset_attribute_string( loc_id, dset_name, "IMAGE_SUBCLASS", "IMAGE_TRUECOLOR" ) < 0)
  return -1;

 /* Attach the INTERLACE_MODE attribute. This attributes is only for true color images */
 if ( H5LTset_attribute_string( loc_id, dset_name, "INTERLACE_MODE", interlace ) < 0)
  return -1;

 return 0;

}



/*-------------------------------------------------------------------------
 * Function: find_palette
 *
 * Purpose: operator function used by H5LT_find_palette
 *
 * Return:
 *
 * Programmer: Pedro Vicente Nunes, pvn@ncsa.uiuc.edu
 *
 * Date: May 28, 2001
 *
 * Comments:
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */
static herr_t
find_palette(hid_t loc_id, const char *name, const H5A_info_t *ainfo,
    void *op_data)
{
    int ret = H5_ITER_CONT;

    /* Shut compiler up */
    loc_id = loc_id; ainfo = ainfo; op_data = op_data;

    /* Define a positive value for return value if the attribute was found. This will
     * cause the iterator to immediately return that positive value,
     * indicating short-circuit success
     */
    if(strcmp(name, "PALETTE") == 0)
        ret = H5_ITER_STOP;

    return ret;
}


/*-------------------------------------------------------------------------
 * Function: H5IM_find_palette
 *
 * Purpose: Private function. Find the attribute "PALETTE" in the image dataset
 *
 * Return: Success: 1, Failure: 0
 *
 * Programmer: Pedro Vicente Nunes, pvn@ncsa.uiuc.edu
 *
 * Date: May 11, 2001
 *
 * Comments:
 *  The function uses H5Aiterate2 with the operator function find_palette
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */

herr_t H5IM_find_palette( hid_t loc_id )
{
    return H5Aiterate2(loc_id, H5_INDEX_NAME, H5_ITER_INC, NULL, find_palette, NULL);
}


/*-------------------------------------------------------------------------
 * Function: H5IMget_image_info
 *
 * Purpose: Gets information about an image dataset (dimensions, interlace mode
 *          and number of associated palettes).
 *
 * Return: Success: 0, Failure: -1
 *
 * Programmer: Pedro Vicente Nunes, pvn@ncsa.uiuc.edu
 *
 * Date: July 25, 2001
 *
 * Comments:
 *  based on HDF5 Image and Palette Specification
 *  http://hdf.ncsa.uiuc.edu/HDF5/H5Image/ImageSpec.html
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */

herr_t H5IMget_image_info( hid_t loc_id,
                           const char *dset_name,
                           hsize_t *width,
                           hsize_t *height,
                           hsize_t *planes,
                           char *interlace,
                           hssize_t *npals )
{
 hid_t   did, sid;
 hsize_t dims[IMAGE24_RANK];
 hid_t   attr_id;
 hid_t   attr_type;
 int     has_attr;
 hid_t   attr_space_id;
 hid_t   attr_class;
 int     has_pal;

 /*assume initially we have no palettes attached*/
 *npals = 0;

 /* Open the dataset. */
 if((did = H5Dopen2(loc_id, dset_name, H5P_DEFAULT)) < 0)
  return -1;

 /* Try to find the attribute "INTERLACE_MODE" on the >>image<< dataset */
 has_attr = H5LT_find_attribute(did, "INTERLACE_MODE");

 /* It exists, get it */
 if(has_attr == 1)
 {

  if((attr_id = H5Aopen(did, "INTERLACE_MODE", H5P_DEFAULT)) < 0)
   goto out;

  if((attr_type = H5Aget_type(attr_id)) < 0)
   goto out;

  if(H5Aread(attr_id, attr_type, interlace) < 0)
   goto out;

  if(H5Tclose(attr_type) < 0)
   goto out;

  if(H5Aclose(attr_id) < 0)
   goto out;
 }

 /* Get the dataspace handle */
 if ( (sid = H5Dget_space( did )) < 0)
  goto out;

 /* Get dimensions */
 if ( H5Sget_simple_extent_dims( sid, dims, NULL) < 0)
  goto out;

 /* Initialize the image dimensions */

 if ( has_attr == 1 )
 /* This is a 24 bit image */
 {

  if ( strcmp( interlace, "INTERLACE_PIXEL" ) == 0 )
  {
   /* Number of color planes is defined as the third dimension */
   *height = dims[0];
   *width  = dims[1];
   *planes = dims[2];
  }
  else
  if ( strcmp( interlace, "INTERLACE_PLANE" ) == 0 )
  {
   /* Number of color planes is defined as the first dimension */
   *planes = dims[0];
   *height = dims[1];
   *width  = dims[2];
  }
  else return -1;
 }
 else
 /* This is a 8 bit image */
 {
  *height = dims[0];
  *width  = dims[1];
  *planes = 1;
 }

 /* Close */
 if ( H5Sclose( sid ) < 0)
  goto out;


 /* Get number of palettes */


 /* Try to find the attribute "PALETTE" on the >>image<< dataset */
 has_pal = H5IM_find_palette(did);

 if(has_pal ==  1)
 {

  if((attr_id = H5Aopen(did, "PALETTE", H5P_DEFAULT)) < 0)
   goto out;

  if((attr_type = H5Aget_type(attr_id)) < 0)
   goto out;

  if((attr_class = H5Tget_class(attr_type)) < 0)
   goto out;

  /* Check if it is really a reference */

  if(attr_class == H5T_REFERENCE)
  {

   /* Get the reference(s) */

   if ( (attr_space_id = H5Aget_space( attr_id )) < 0)
    goto out;

   *npals = H5Sget_simple_extent_npoints( attr_space_id );

   if ( H5Sclose( attr_space_id ) < 0)
    goto out;

  } /* H5T_REFERENCE */

  if ( H5Tclose( attr_type ) < 0)
   goto out;

  /* Close the attribute. */
  if ( H5Aclose( attr_id ) < 0)
   goto out;

 }

 /* End access to the dataset and release resources used by it. */
 if ( H5Dclose( did ) < 0)
  goto out;

 return 0;

out:
 H5Dclose( did );
 return -1;

}


/*-------------------------------------------------------------------------
 * Function: H5IMread_image
 *
 * Purpose: Reads image data from disk.
 *
 * Return: Success: 0, Failure: -1
 *
 * Programmer: Pedro Vicente Nunes, pvn@ncsa.uiuc.edu
 *
 * Date: June 13, 2001
 *
 * Comments:
 *  based on HDF5 Image and Palette Specification
 *  http://hdf.ncsa.uiuc.edu/HDF5/H5Image/ImageSpec.html
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */

herr_t H5IMread_image( hid_t loc_id,
                       const char *dset_name,
                       unsigned char *buffer )
{
 hid_t   did;

 /* Open the dataset. */
 if((did = H5Dopen2(loc_id, dset_name, H5P_DEFAULT)) < 0)
  return -1;

 /* Read */
 if ( H5Dread( did, H5T_NATIVE_UCHAR, H5S_ALL, H5S_ALL, H5P_DEFAULT, buffer ) < 0)
  goto out;

 /* End access to the dataset and release resources used by it. */
 if ( H5Dclose( did ) )
  return -1;

 return 0;

out:
 H5Dclose( did );
 return -1;

}


/*-------------------------------------------------------------------------
 * Function: H5IMmake_palette
 *
 * Purpose: Creates and writes a palette.
 *
 * Return: Success: 0, Failure: -1
 *
 * Programmer: Pedro Vicente Nunes, pvn@ncsa.uiuc.edu
 *
 * Date: May 01, 2001
 *
 * Comments:
 *  based on HDF5 Image and Palette Specification
 *  http://hdf.ncsa.uiuc.edu/HDF5/H5Image/ImageSpec.html
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */

herr_t H5IMmake_palette( hid_t loc_id,
                         const char *pal_name,
                         const hsize_t *pal_dims,
                         const unsigned char *pal_data )

{

 int has_pal;

 /* Check if the dataset already exists */
 has_pal = H5LTfind_dataset( loc_id, pal_name );

 /* It exists. Return */
 if ( has_pal == 1 )
  return 0;

 /* Make the palette dataset. */
 if ( H5LTmake_dataset( loc_id, pal_name, 2, pal_dims, H5T_NATIVE_UCHAR, pal_data ) <  0 )
  return -1;

 /* Attach the attribute "CLASS" to the >>palette<< dataset*/
 if ( H5LTset_attribute_string( loc_id, pal_name, "CLASS", PALETTE_CLASS ) < 0)
  return -1;

 /* Attach the attribute "PAL_VERSION" to the >>palette<< dataset*/
 if ( H5LTset_attribute_string( loc_id, pal_name, "PAL_VERSION", "1.2" ) < 0)
  return -1;

 return 0;

}


/*-------------------------------------------------------------------------
 * Function: H5IMlink_palette
 *
 * Purpose: This function attaches a palette to an existing image dataset
 *
 * Return: Success: 0, Failure: -1
 *
 * Programmer: Pedro Vicente Nunes, pvn@ncsa.uiuc.edu
 *
 * Date: May 01, 2001
 *
 * Comments:
 *  based on HDF5 Image and Palette Specification
 *  http://hdf.ncsa.uiuc.edu/HDF5/H5Image/ImageSpec.html
 *
 *  An image (dataset) within an HDF5 file may optionally specify an array of
 *  palettes to be viewed with. The dataset will have an attribute
 *  which contains an array of object reference pointers which refer to palettes in the file.
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */

herr_t H5IMlink_palette( hid_t loc_id,
                         const char *image_name,
                         const char *pal_name )

{
 hid_t       image_id;
 hid_t       attr_type=-1;
 hid_t       attr_id=-1;
 hid_t       attr_space_id=-1;
 hid_t       attr_class=-1;
 hobj_ref_t  ref;         /* write a new reference */
 hobj_ref_t  *refbuf;     /* buffer to read references */
 hssize_t    n_refs;
 hsize_t     dim_ref;
 int         ok_pal;

 /* The image dataset may or may not have the attribute "PALETTE"
  * First we try to open to see if it is already there; if not, it is created.
  * If it exists, the array of references is extended to hold the reference
  * to the new palette
  */

 /* First we get the image id */
 if((image_id = H5Dopen2(loc_id, image_name, H5P_DEFAULT)) < 0)
  return -1;

 /* Try to find the attribute "PALETTE" on the >>image<< dataset */
 ok_pal = H5LT_find_attribute( image_id, "PALETTE" );

/*-------------------------------------------------------------------------
 * It does not exist. We create the attribute and one reference
 *-------------------------------------------------------------------------
 */
 if(ok_pal == 0 )
 {
  if((attr_space_id = H5Screate(H5S_SCALAR)) < 0)
   goto out;

  /* Create the attribute type for the reference */
  if((attr_type = H5Tcopy(H5T_STD_REF_OBJ)) < 0)
   goto out;

  /* Create the attribute "PALETTE" to be attached to the image*/
  if((attr_id = H5Acreate2(image_id, "PALETTE", attr_type, attr_space_id, H5P_DEFAULT, H5P_DEFAULT)) < 0)
   goto out;

  /* Create a reference. The reference is created on the local id.  */
  if(H5Rcreate(&ref, loc_id, pal_name, H5R_OBJECT, -1) < 0)
   goto out;

  /* Write the attribute with the reference */
  if(H5Awrite(attr_id, attr_type, &ref) < 0)
   goto out;

  /* close */
  if(H5Sclose(attr_space_id) < 0)
   goto out;
  if ( H5Tclose( attr_type ) < 0)
   goto out;
  if(H5Aclose(attr_id) < 0)
   goto out;

 }

/*-------------------------------------------------------------------------
 * The attribute already exists, open it
 *-------------------------------------------------------------------------
 */
 else if(ok_pal ==  1)
 {
  if((attr_id = H5Aopen(image_id, "PALETTE", H5P_DEFAULT)) < 0)
   goto out;
  
  if((attr_type = H5Aget_type(attr_id)) < 0)
   goto out;
  
  if((attr_class = H5Tget_class(attr_type)) < 0)
   goto out;
  
  /* Get and save the old reference(s) */
  if((attr_space_id = H5Aget_space(attr_id)) < 0)
   goto out;
  
  n_refs = H5Sget_simple_extent_npoints(attr_space_id);
  
  dim_ref = n_refs + 1;
  
  refbuf = malloc( sizeof(hobj_ref_t) * (int)dim_ref );
  
  if ( H5Aread( attr_id, attr_type, refbuf ) < 0)
   goto out;
 
  /* The attribute must be deleted, in order to the new one can reflect the changes*/
  if(H5Adelete(image_id, "PALETTE") < 0)
   goto out;
  
  /* Create a new reference for this palette. */
  if ( H5Rcreate( &ref, loc_id, pal_name, H5R_OBJECT, -1 ) < 0)
   goto out;
  
  refbuf[n_refs] = ref;
  
  /* Create the data space for the new references */
  if(H5Sclose(attr_space_id) < 0)
   goto out;
  
  if((attr_space_id = H5Screate_simple(1, &dim_ref, NULL)) < 0)
   goto out;
  
  /* Create the attribute again with the changes of space */
  if(H5Aclose(attr_id) < 0)
   goto out;

  if((attr_id = H5Acreate2(image_id, "PALETTE", attr_type, attr_space_id, H5P_DEFAULT, H5P_DEFAULT)) < 0)
   goto out;
  
  /* Write the attribute with the new references */
  if(H5Awrite(attr_id, attr_type, refbuf) < 0)
   goto out;
  
  /* close */
  if(H5Sclose(attr_space_id) < 0)
   goto out;
  if(H5Aclose(attr_id) < 0)
   goto out;
  
  free( refbuf );
 
 } /* ok_pal ==  1 */

  /* Close the image dataset. */
 if ( H5Dclose( image_id ) < 0)
  return -1;

 return 0;

out:
 H5Dclose( image_id );
 H5Sclose( attr_space_id );
 H5Tclose( attr_type );
 H5Aclose( attr_id );
 return -1;
}



/*-------------------------------------------------------------------------
 * Function: H5IMunlink_palette
 *
 * Purpose: This function dettaches a palette from an existing image dataset
 *
 * Return: Success: 0, Failure: -1
 *
 * Programmer: Pedro Vicente Nunes, pvn@ncsa.uiuc.edu
 *
 * Date: September 10, 2001
 *
 * Comments:
 *  based on HDF5 Image and Palette Specification
 *  http://hdf.ncsa.uiuc.edu/HDF5/H5Image/ImageSpec.html
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */

herr_t H5IMunlink_palette( hid_t loc_id,
                           const char *image_name,
                           const char *pal_name )
{
 hid_t       image_id;
 hid_t       attr_type;
 hid_t       attr_id;
 hid_t       attr_class;
 int         ok_pal, has_pal;

 /* Try to find the palette dataset */
 has_pal = H5LTfind_dataset( loc_id, pal_name );

 /* It does not exist. Return */
 if ( has_pal == 0 )
  return -1;

 /* The image dataset may or not have the attribute "PALETTE"
  * First we try to open to see if it is already there; if not, it is created.
  * If it exists, the array of references is extended to hold the reference
  * to the new palette
  */

 /* First we get the image id */
 if((image_id = H5Dopen2(loc_id, image_name, H5P_DEFAULT)) < 0)
  return -1;

 /* Try to find the attribute "PALETTE" on the >>image<< dataset */
 ok_pal = H5LT_find_attribute(image_id, "PALETTE");

 /* It does not exist. Nothing to do */
 if(ok_pal == 0)
  return -1;

 /* The attribute exists, open it */
 else if(ok_pal ==  1)
 {
  if((attr_id = H5Aopen(image_id, "PALETTE", H5P_DEFAULT)) < 0)
   goto out;

  if((attr_type = H5Aget_type(attr_id)) < 0)
   goto out;

  if((attr_class = H5Tget_class(attr_type)) < 0)
   goto out;

  /* Check if it is really a reference */
  if(attr_class == H5T_REFERENCE)
  {
   /* Delete the attribute */
   if(H5Adelete(image_id, "PALETTE") < 0)
    goto out;

  }  /* H5T_REFERENCE */

  if(H5Tclose(attr_type) < 0)
   goto out;

  /* Close the attribute. */
  if(H5Aclose(attr_id) < 0)
   goto out;

 } /* ok_pal */

  /* Close the image dataset. */
 if(H5Dclose(image_id) < 0)
  return -1;

 return 0;

out:
 H5Dclose( image_id );
 return -1;
}


/*-------------------------------------------------------------------------
 * Function: H5IMget_npalettes
 *
 * Purpose: Gets the number of palettes associated to an image
 *
 * Return: Success: 0, Failure: -1
 *
 * Programmer: Pedro Vicente Nunes, pvn@ncsa.uiuc.edu
 *
 * Date: July 22, 2001
 *
 * Comments:
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */

herr_t H5IMget_npalettes( hid_t loc_id,
                          const char *image_name,
                          hssize_t *npals )
{
 hid_t      image_id;
 hid_t      attr_type;
 hid_t      attr_id;
 hid_t      attr_space_id;
 hid_t      attr_class;
 int        has_pal;

 /*assume initially we have no palettes attached*/
 *npals = 0;

 /* Open the dataset. */
 if((image_id = H5Dopen2(loc_id, image_name, H5P_DEFAULT)) < 0)
  return -1;

 /* Try to find the attribute "PALETTE" on the >>image<< dataset */
 has_pal = H5IM_find_palette(image_id);

 if(has_pal ==  1 )
 {

  if((attr_id = H5Aopen(image_id, "PALETTE", H5P_DEFAULT)) < 0)
   goto out;

  if((attr_type = H5Aget_type(attr_id)) < 0)
   goto out;

  if((attr_class = H5Tget_class(attr_type)) < 0)
   goto out;

  /* Check if it is really a reference */

  if(attr_class == H5T_REFERENCE)
  {
   if((attr_space_id = H5Aget_space(attr_id)) < 0)
    goto out;

   *npals = H5Sget_simple_extent_npoints( attr_space_id );

   if ( H5Sclose( attr_space_id ) < 0)
    goto out;

  } /* H5T_REFERENCE */

  if ( H5Tclose( attr_type ) < 0)
   goto out;

  /* Close the attribute. */
  if ( H5Aclose( attr_id ) < 0)
   goto out;

 }

     /* Close the image dataset. */
 if ( H5Dclose( image_id ) < 0)
  return -1;

 return 0;

out:
 H5Dclose( image_id );
 return -1;

}


/*-------------------------------------------------------------------------
 * Function: H5IMget_palette_info
 *
 * Purpose: Get palette information
 *
 * Return: Success: 0, Failure: -1
 *
 * Programmer: Pedro Vicente Nunes, pvn@ncsa.uiuc.edu
 *
 * Date: July 22, 2001
 *
 * Comments:
 *  based on HDF5 Image and Palette Specification
 *  http://hdf.ncsa.uiuc.edu/HDF5/H5Image/ImageSpec.html
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */

herr_t H5IMget_palette_info( hid_t loc_id,
                             const char *image_name,
                             int pal_number,
                             hsize_t *pal_dims )
{
 hid_t      image_id;
 int        has_pal;
 hid_t      attr_type=-1;
 hid_t      attr_id;
 hid_t      attr_space_id=-1;
 hid_t      attr_class;
 hssize_t   n_refs;
 hsize_t    dim_ref;
 hobj_ref_t *refbuf;     /* buffer to read references */
 hid_t      pal_id;
 hid_t      pal_space_id;
 hsize_t    pal_maxdims[2];
 
 /* Open the dataset. */
 if((image_id = H5Dopen2(loc_id, image_name, H5P_DEFAULT)) < 0)
  return -1;
 
 /* Try to find the attribute "PALETTE" on the >>image<< dataset */
 has_pal = H5IM_find_palette(image_id);
 
 if(has_pal ==  1)
 {
  if((attr_id = H5Aopen(image_id, "PALETTE", H5P_DEFAULT)) < 0)
   goto out;
  
  if((attr_type = H5Aget_type(attr_id)) < 0)
   goto out;
  
  if((attr_class = H5Tget_class(attr_type)) < 0)
   goto out;
  
  /* Get the reference(s) */
  if((attr_space_id = H5Aget_space(attr_id)) < 0)
   goto out;
  
  n_refs = H5Sget_simple_extent_npoints(attr_space_id);
  
  dim_ref = n_refs;
  
  refbuf = malloc( sizeof(hobj_ref_t) * (int)dim_ref );
  
  if ( H5Aread( attr_id, attr_type, refbuf ) < 0)
   goto out;
  
  /* Get the actual palette */
  if ( (pal_id = H5Rdereference( image_id, H5R_OBJECT, &refbuf[pal_number] )) < 0)
   goto out;
  
  if ( (pal_space_id = H5Dget_space( pal_id )) < 0)
   goto out;
  
  if ( H5Sget_simple_extent_ndims( pal_space_id ) < 0)
   goto out;
  
  if ( H5Sget_simple_extent_dims( pal_space_id, pal_dims, pal_maxdims ) < 0)
   goto out;
  
  /* close */
  if (H5Dclose(pal_id)<0)
   goto out;
  if ( H5Sclose( pal_space_id ) < 0)
   goto out;
  if ( H5Sclose( attr_space_id ) < 0)
   goto out;
  if ( H5Tclose( attr_type ) < 0)
   goto out;
  if ( H5Aclose( attr_id ) < 0)
   goto out;
  free( refbuf );
  
   
 }
 
 /* Close the image dataset. */
 if ( H5Dclose( image_id ) < 0)
  return -1;
 
 return 0;
 
out:
 H5Dclose( image_id );
 H5Sclose( attr_space_id );
 H5Tclose( attr_type );
 H5Aclose( attr_id );
 return -1;
 
}


/*-------------------------------------------------------------------------
 * Function: H5IMget_palette
 *
 * Purpose: Read palette
 *
 * Return: Success: 0, Failure: -1
 *
 * Programmer: Pedro Vicente Nunes, pvn@ncsa.uiuc.edu
 *
 * Date: August 30, 2001
 *
 * Comments:
 *  based on HDF5 Image and Palette Specification
 *  http://hdf.ncsa.uiuc.edu/HDF5/H5Image/ImageSpec.html
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */

herr_t H5IMget_palette( hid_t loc_id,
                        const char *image_name,
                        int pal_number,
                        unsigned char *pal_data )
{
 hid_t      image_id;
 int        has_pal;
 hid_t      attr_type=-1;
 hid_t      attr_id;
 hid_t      attr_space_id=-1;
 hid_t      attr_class;
 hssize_t   n_refs;
 hsize_t    dim_ref;
 hobj_ref_t *refbuf;     /* buffer to read references */
 hid_t      pal_id;

 /* Open the dataset. */
 if((image_id = H5Dopen2(loc_id, image_name, H5P_DEFAULT)) < 0)
  return -1;

 /* Try to find the attribute "PALETTE" on the >>image<< dataset */
 has_pal = H5IM_find_palette(image_id);

 if(has_pal ==  1 )
 {
  if((attr_id = H5Aopen(image_id, "PALETTE", H5P_DEFAULT)) < 0)
   goto out;
  
  if((attr_type = H5Aget_type(attr_id)) < 0)
   goto out;
  
  if((attr_class = H5Tget_class(attr_type)) < 0)
   goto out;
  
  /* Get the reference(s) */
  if((attr_space_id = H5Aget_space(attr_id)) < 0)
   goto out;
  
  n_refs = H5Sget_simple_extent_npoints(attr_space_id);
  
  dim_ref = n_refs;
  
  refbuf = malloc( sizeof(hobj_ref_t) * (int)dim_ref );
  
  if ( H5Aread( attr_id, attr_type, refbuf ) < 0)
   goto out;
  
  /* Get the palette id */
  if ( (pal_id = H5Rdereference( image_id, H5R_OBJECT, &refbuf[pal_number] )) < 0)
   goto out;
  
  /* Read the palette dataset */
  if ( H5Dread( pal_id, H5Dget_type(pal_id), H5S_ALL, H5S_ALL, H5P_DEFAULT, pal_data ) < 0)
   goto out;

  /* close */
  if (H5Dclose(pal_id)<0)
   goto out;
  if ( H5Sclose( attr_space_id ) < 0)
   goto out;
  if ( H5Tclose( attr_type ) < 0)
   goto out;
  if ( H5Aclose( attr_id ) < 0)
   goto out;
  free( refbuf );
 }

 /* Close the image dataset. */
 if ( H5Dclose( image_id ) < 0)
  return -1;

 return 0;

out:
 H5Dclose( image_id );
 H5Sclose( attr_space_id );
 H5Tclose( attr_type );
 H5Aclose( attr_id );
 return -1;

}

/*-------------------------------------------------------------------------
 * Function: H5IMis_image
 *
 * Purpose:
 *
 * Return: true, false, fail
 *
 * Programmer: Pedro Vicente Nunes, pvn@ncsa.uiuc.edu
 *
 * Date: August 30, 2001
 *
 * Comments:
 *  based on HDF5 Image and Palette Specification
 *  http://hdf.ncsa.uiuc.edu/HDF5/H5Image/ImageSpec.html
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */

herr_t H5IMis_image( hid_t loc_id,
                     const char *dset_name )
{
 hid_t      did;
 int        has_class;
 hid_t      attr_type;
 hid_t      attr_id;
 char       attr_data[20];
 herr_t     ret;

 /* Assume initially fail condition */
 ret = -1;

 /* Open the dataset. */
 if((did = H5Dopen2(loc_id, dset_name, H5P_DEFAULT)) < 0)
  return -1;

 /* Try to find the attribute "CLASS" on the dataset */
 has_class = H5LT_find_attribute(did, "CLASS");

 if(has_class == 0)
 {
  H5Dclose(did);
  return 0;
 }
 else if(has_class ==  1)
 {

  if((attr_id = H5Aopen(did, "CLASS", H5P_DEFAULT)) < 0)
   goto out;

  if((attr_type = H5Aget_type(attr_id)) < 0)
   goto out;

  if(H5Tget_class(attr_type) < 0)
   goto out;

  if(H5Aread(attr_id, attr_type, attr_data) < 0)
    goto out;

  if(strcmp(attr_data, IMAGE_CLASS) == 0)
   ret = 1;
  else
   ret = 0;

  if ( H5Tclose( attr_type ) < 0)
   goto out;

  if ( H5Aclose( attr_id ) < 0)
   goto out;

 }

 /* Close the dataset. */
 if ( H5Dclose( did ) < 0)
  return -1;

 return ret;

out:
 H5Dclose( did );
 return -1;

}

/*-------------------------------------------------------------------------
 * Function: H5IMis_palette
 *
 * Purpose:
 *
 * Return: true, false, fail
 *
 * Programmer: Pedro Vicente Nunes, pvn@ncsa.uiuc.edu
 *
 * Date: August 30, 2001
 *
 * Comments:
 *  based on HDF5 Image and Palette Specification
 *  http://hdf.ncsa.uiuc.edu/HDF5/H5Image/ImageSpec.html
 *
 * Modifications:
 *
 *-------------------------------------------------------------------------
 */

herr_t H5IMis_palette( hid_t loc_id,
                       const char *dset_name )
{
 hid_t      did;
 int        has_class;
 hid_t      attr_type;
 hid_t      attr_id;
 char       attr_data[20];
 herr_t     ret;

 /* Assume initially fail condition */
 ret = -1;

 /* Open the dataset. */
 if((did = H5Dopen2(loc_id, dset_name, H5P_DEFAULT)) < 0)
  return -1;

 /* Try to find the attribute "CLASS" on the dataset */
 has_class = H5LT_find_attribute(did, "CLASS");

 if(has_class ==  0)
 {
  H5Dclose( did );
  return 0;
 }
 else if(has_class ==  1)
 {

  if((attr_id = H5Aopen(did, "CLASS", H5P_DEFAULT)) < 0)
   goto out;

  if((attr_type = H5Aget_type(attr_id)) < 0)
   goto out;

  if(H5Tget_class(attr_type) < 0)
   goto out;

  if(H5Aread(attr_id, attr_type, attr_data) < 0)
    goto out;

  if(strcmp(attr_data, PALETTE_CLASS) == 0)
   ret = 1;
  else
   ret = 0;

  if ( H5Tclose( attr_type ) < 0)
   goto out;

  if ( H5Aclose( attr_id ) < 0)
   goto out;

 }

 /* Close the dataset. */
 if ( H5Dclose( did ) < 0)
  return -1;

 return ret;

out:
 H5Dclose( did );
 return -1;

}

